package cn.mesmile.workflow.process.service.impl;

import cn.mesmile.workflow.commom.Query;
import cn.mesmile.workflow.constant.WorkFlowConstant;
import cn.mesmile.workflow.process.bo.OperationTaskBO;
import cn.mesmile.workflow.process.qo.WorkFlowAdminQO;
import cn.mesmile.workflow.process.service.WorkFlowAdminService;
import cn.mesmile.workflow.process.service.WorkFlowService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.history.HistoricProcessInstanceQuery;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * @author zb
 * @Description
 */
@Slf4j
@AllArgsConstructor
@Transactional(rollbackFor = Exception.class, propagation = Propagation.SUPPORTS, readOnly = true)
@Service
public class WorkFlowAdminServiceImpl implements WorkFlowAdminService {

    private final RepositoryService repositoryService;
    private final RuntimeService runtimeService;
    private final TaskService taskService;
    private final HistoryService historyService;
    private final IdentityService identityService;

    private final WorkFlowService workFlowService;

    @Override
    public IPage<Task> listAllTodoTask(Query query, WorkFlowAdminQO workFlowAdminQO) {
        TaskQuery taskQuery = taskService.createTaskQuery()
                .orderByTaskCreateTime().desc();

        String processDefName = workFlowAdminQO.getProcessDefName();
        String processDefKey = workFlowAdminQO.getProcessDefKey();
        String taskName = workFlowAdminQO.getTaskName();
        String applyUser = workFlowAdminQO.getApplyUser();
        Date startDate = workFlowAdminQO.getStartDate();
        Date endDate = workFlowAdminQO.getEndDate();
        String taskId = workFlowAdminQO.getTaskId();
        String assignee = workFlowAdminQO.getAssignee();
        String processInstanceId = workFlowAdminQO.getProcessInstanceId();
        Boolean isSuspended = workFlowAdminQO.getIsSuspended();
        List<String> categoryList = workFlowAdminQO.getCategoryList();
        if (StringUtils.isNotBlank(processDefName)){
            taskQuery.processDefinitionNameLike("%"+processDefName+"%");
        }
        if (StringUtils.isNotBlank(processDefKey)){
            taskQuery.processDefinitionKey(processDefName);
        }
        if (StringUtils.isNotBlank(taskName)){
            taskQuery.taskNameLike("%"+taskName+"%");
        }
        if(StringUtils.isNotBlank(applyUser)){
            taskQuery.processVariableValueEquals(WorkFlowConstant.PROCESS_APPLY_USER, applyUser);
        }
        if (startDate != null){
            taskQuery.taskCreatedAfter(startDate);
        }
        if (endDate != null){
            taskQuery.taskCreatedBefore(endDate);
        }
        if (StringUtils.isNotBlank(taskId)){
            taskQuery.taskId(taskId);
        }
        if (StringUtils.isNotBlank(assignee)){
            taskQuery.taskAssignee(assignee);
        }
        if (StringUtils.isNotBlank(processInstanceId)){
          taskQuery.processInstanceId(processInstanceId);
        }
        if (isSuspended == null || isSuspended){
            taskQuery.active();
        }
        if (categoryList != null && categoryList.size() > 0){
            taskQuery.processCategoryIn(categoryList);
        }
        long total = taskQuery.count();
        Integer current = query.getCurrent();
        Integer size = query.getSize();
        Page<Task> page = Page.of(current, size, total);
        List<Task> tasks = taskQuery.listPage((current - 1) * size, size);
        page.setRecords(tasks);
        return page;
    }

    @Override
    public void urgeTask(OperationTaskBO operationTaskBO) {
        List<String> taskIdList = operationTaskBO.getTaskIdList();
        if (taskIdList != null && taskIdList.size() > 0){
            taskIdList.forEach(taskId ->{
                operationTaskBO.setTaskId(taskId);
                // 催办任务
                workFlowService.urgeTask(operationTaskBO);
            });
        }
    }

    @Override
    public void transferTask(OperationTaskBO operationTaskBO) {
        List<String> taskIdList = operationTaskBO.getTaskIdList();
        if (taskIdList != null && taskIdList.size() > 0){
            taskIdList.forEach(taskId -> {
                operationTaskBO.setTaskId(taskId);
                // 转办任务
                workFlowService.transferTask(operationTaskBO);
            });
        }
    }

    @Override
    public void delegateTask(OperationTaskBO operationTaskBO) {
        List<String> taskIdList = operationTaskBO.getTaskIdList();
        if (taskIdList != null && taskIdList.size() > 0){
            taskIdList.forEach(taskId -> {
                operationTaskBO.setTaskId(taskId);
                // 委托任务
                workFlowService.delegateTask(operationTaskBO);
            });
        }
    }

    @Override
    public void terminationTask(OperationTaskBO operationTaskBO) {
        List<String> taskIdList = operationTaskBO.getTaskIdList();
        if (taskIdList != null && taskIdList.size() > 0) {
            taskIdList.forEach(taskId -> {
                operationTaskBO.setTaskId(taskId);
                // 终止任务
                workFlowService.terminationTask(operationTaskBO);
            });
        }
    }

    @Override
    public void addMultiInstance(OperationTaskBO operationTaskBO) {
        List<String> taskIdList = operationTaskBO.getTaskIdList();
        if (taskIdList != null && taskIdList.size() > 0) {
            taskIdList.forEach(taskId -> {
                operationTaskBO.setTaskId(taskId);
                // 加签任务
                workFlowService.addMultiInstance(operationTaskBO);
            });
        }
    }

    @Override
    public void deleteMultiInstance(OperationTaskBO operationTaskBO) {
        List<String> taskIdList = operationTaskBO.getTaskIdList();
        if (taskIdList != null && taskIdList.size() > 0) {
            taskIdList.forEach(taskId -> {
                operationTaskBO.setTaskId(taskId);
                // 减签任务
                workFlowService.deleteMultiInstance(operationTaskBO);
            });
        }
    }

    @Override
    public void rollbackTask(OperationTaskBO operationTaskBO) {
        // 回退任务
        workFlowService.rollbackTask(operationTaskBO);
    }

    @Override
    public IPage<HistoricProcessInstance> listAllDoneTask(Query query, WorkFlowAdminQO workFlowAdminQO) {
        HistoricProcessInstanceQuery processInstanceQuery = historyService.createHistoricProcessInstanceQuery()
                .finished().orderByProcessInstanceEndTime().desc();

        String processInstanceId = workFlowAdminQO.getProcessInstanceId();
        String processDefName = workFlowAdminQO.getProcessDefName();
        String processDefKey = workFlowAdminQO.getProcessDefKey();
        String applyUser = workFlowAdminQO.getApplyUser();
        Date startDate = workFlowAdminQO.getStartDate();
        Date endDate = workFlowAdminQO.getEndDate();

        if (StringUtils.isNotBlank(processInstanceId)) {
            processInstanceQuery.processInstanceId(processInstanceId);
        }
        if (StringUtils.isNotBlank(processDefName)) {
            processInstanceQuery.processDefinitionName(processDefName);
        }
        if (StringUtils.isNotBlank(processDefKey)) {
            processInstanceQuery.processDefinitionKey(processDefKey);
        }
        if (StringUtils.isNotBlank(applyUser)) {
            processInstanceQuery.variableValueEquals(WorkFlowConstant.PROCESS_APPLY_USER, applyUser);
        }
        if (startDate != null){
            processInstanceQuery.startedAfter(startDate);
        }
        if (endDate != null) {
            processInstanceQuery.startedBefore(endDate);
        }
        long total = processInstanceQuery.count();
        Integer current = query.getCurrent();
        Integer size = query.getSize();
        Page<HistoricProcessInstance> page = Page.of(current, size, total);
        List<HistoricProcessInstance> historicProcessInstances = processInstanceQuery.listPage((current - 1) * size, size);
        page.setRecords(historicProcessInstances);

        return page;
    }


}
